import { createClient } from 'redis'
import { config } from '@/config/env'

// Redis 客户端类型 - 使用 createClient 的返回类型
type RedisClient = ReturnType<typeof createClient>

// 创建 Redis 客户端
const createRedisClient = (): RedisClient => {
  const client = createClient({
    url: config.redis.url,
    socket: {
      reconnectStrategy: (retries) => {
        if (retries > 10) {
          console.error('Redis reconnection failed after 10 attempts')
          return new Error('Redis reconnection failed')
        }
        return Math.min(retries * 50, 1000)
      },
    },
  })

  // 错误处理
  client.on('error', (err) => {
    console.error('Redis Client Error:', err)
  })

  client.on('connect', () => {
    console.log('Redis Client Connected')
  })

  client.on('ready', () => {
    console.log('Redis Client Ready')
  })

  client.on('end', () => {
    console.log('Redis Client Disconnected')
  })

  return client
}

// 单例 Redis 客户端
let redisClient: RedisClient | null = null

// 获取 Redis 客户端
export const getRedisClient = async (): Promise<RedisClient> => {
  if (!redisClient) {
    redisClient = createRedisClient()
    await redisClient.connect()
  }
  return redisClient
}

// Redis 缓存辅助类
export class RedisCache {
  private client: RedisClient | null = null
  private prefix: string

  constructor(prefix: string = config.redis.prefix) {
    this.prefix = prefix
  }

  private async getClient(): Promise<RedisClient> {
    if (!this.client) {
      this.client = await getRedisClient()
    }
    return this.client
  }

  private getKey(key: string): string {
    return `${this.prefix}${key}`
  }

  // 设置缓存
  async set(key: string, value: any, ttl?: number): Promise<void> {
    const client = await this.getClient()
    const serializedValue = JSON.stringify(value)
    
    if (ttl) {
      await client.setEx(this.getKey(key), ttl, serializedValue)
    } else {
      await client.set(this.getKey(key), serializedValue)
    }
  }

  // 获取缓存
  async get<T = any>(key: string): Promise<T | null> {
    const client = await this.getClient()
    const value = await client.get(this.getKey(key))
    
    if (!value) {
      return null
    }

    try {
      return JSON.parse(value) as T
    } catch (error) {
      console.error('Error parsing cached value:', error)
      return null
    }
  }

  // 删除缓存
  async del(key: string): Promise<void> {
    const client = await this.getClient()
    await client.del(this.getKey(key))
  }

  // 检查缓存是否存在
  async exists(key: string): Promise<boolean> {
    const client = await this.getClient()
    const result = await client.exists(this.getKey(key))
    return result === 1
  }

  // 设置过期时间
  async expire(key: string, ttl: number): Promise<void> {
    const client = await this.getClient()
    await client.expire(this.getKey(key), ttl)
  }

  // 获取剩余过期时间
  async ttl(key: string): Promise<number> {
    const client = await this.getClient()
    return await client.ttl(this.getKey(key))
  }

  // 批量删除
  async delPattern(pattern: string): Promise<void> {
    const client = await this.getClient()
    const keys = await client.keys(this.getKey(pattern))
    
    if (keys.length > 0) {
      await client.del(keys)
    }
  }

  // 增加计数器
  async incr(key: string, increment: number = 1): Promise<number> {
    const client = await this.getClient()
    return await client.incrBy(this.getKey(key), increment)
  }

  // 减少计数器
  async decr(key: string, decrement: number = 1): Promise<number> {
    const client = await this.getClient()
    return await client.decrBy(this.getKey(key), decrement)
  }

  // 列表操作
  async lpush(key: string, ...values: string[]): Promise<number> {
    const client = await this.getClient()
    return await client.lPush(this.getKey(key), values)
  }

  async rpush(key: string, ...values: string[]): Promise<number> {
    const client = await this.getClient()
    return await client.rPush(this.getKey(key), values)
  }

  async lpop(key: string): Promise<string | null> {
    const client = await this.getClient()
    return await client.lPop(this.getKey(key))
  }

  async rpop(key: string): Promise<string | null> {
    const client = await this.getClient()
    return await client.rPop(this.getKey(key))
  }

  async lrange(key: string, start: number, stop: number): Promise<string[]> {
    const client = await this.getClient()
    return await client.lRange(this.getKey(key), start, stop)
  }

  // 集合操作
  async sadd(key: string, ...members: string[]): Promise<number> {
    const client = await this.getClient()
    return await client.sAdd(this.getKey(key), members)
  }

  async srem(key: string, ...members: string[]): Promise<number> {
    const client = await this.getClient()
    return await client.sRem(this.getKey(key), members)
  }

  async smembers(key: string): Promise<string[]> {
    const client = await this.getClient()
    return await client.sMembers(this.getKey(key))
  }

  async sismember(key: string, member: string): Promise<boolean> {
    const client = await this.getClient()
    return await client.sIsMember(this.getKey(key), member)
  }
}

// 默认缓存实例
export const cache = new RedisCache()

// Redis 健康检查
export const checkRedisConnection = async (): Promise<boolean> => {
  try {
    const client = await getRedisClient()
    await client.ping()
    return true
  } catch (error) {
    console.error('Redis connection failed:', error)
    return false
  }
}

// 关闭 Redis 连接
export const closeRedisConnection = async (): Promise<void> => {
  if (redisClient) {
    try {
      await redisClient.quit()
      redisClient = null
      console.log('Redis connection closed')
    } catch (error) {
      console.error('Error closing Redis connection:', error)
    }
  }
}

// 进程退出时关闭 Redis 连接
process.on('beforeExit', async () => {
  await closeRedisConnection()
})

process.on('SIGINT', async () => {
  await closeRedisConnection()
})

process.on('SIGTERM', async () => {
  await closeRedisConnection()
})
